/**************************************************************************************************
	$Header: /pub/cvsroot/mydns/lib/error.c,v 1.13 2002/06/23 01:01:09 bboy Exp $
	error.c: Error reporting and message output functions.

	Copyright (C) 2002  Don Moore <bboy@bboy.net>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at Your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
**************************************************************************************************/

#include "mydnsutil.h"

/* The name of the currently running program */
char	*progname = PACKAGE;

/* Should ERR_VERBOSE cause output? */
int	err_verbose = 0;

/* Should ERR_DEBUG cause output? */
int	err_debug = 0;


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	ERROR_INIT
	Initialize error reporting and output functions.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void
error_init(argv0, facility)
	const char *argv0;	/* argv[0] from calling program */
	int facility;			/* Logging facility (i.e. LOG_DAEMON, etc) */
{
	int option;

	/* Save program name */
	if (argv0)
	{
		char *c;
		if ((c = strrchr(argv0, '/')))
			progname = xstrdup(c+1);
		else
			progname = xstrdup((char *)argv0);
	}

	/* Open syslog */
	option = LOG_CONS | LOG_NDELAY | LOG_PID;
	if (isatty(STDERR_FILENO))
		option |= LOG_PERROR;
	openlog(progname, option, facility);
}
/*--- error_init() ------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	_ERROR_OUT
	This function handles all program output after command line handling.
	Always returns -1.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int
_error_out(
	int priority,				/* Priority (i.e. LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG) */
	int errappend,				/* Append strerror(errno)? */
	int isfatal,				/* Is this error fatal? */
	const char *sourcefile,	/* Source file name (__FILE__) */
	unsigned int lineno,		/* Source file line number (__LINE__) */
	const char *fmt, ...
)
{
#if HAVE_VASPRINTF
	char *msg = NULL;
#else
	char msg[BUFSIZ] = "\0";
#endif
	va_list ap;

	if (priority == LOG_DEBUG && !err_debug)
		return (-1);
	if (priority == LOG_INFO && !err_verbose)
		return (-1);

	/* Construct output string */
	va_start(ap, fmt);
#if HAVE_VASPRINTF
	vasprintf(&msg, fmt, ap);
#else
	vsnprintf(msg, sizeof(msg), fmt, ap);
#endif
	va_end(ap);

	/* Debug() output: no syslog, append source info */
	if (priority == LOG_DEBUG)
	{
		if (!stdout) return (-1);
		if (errappend)
			fprintf(stdout, "%s[%u]: %s: %s (%s:%u)\n", progname, getpid(), msg, strerror(errno), sourcefile, lineno);
		else
			fprintf(stdout, "%s[%u]: %s (%s:%u)\n", progname, getpid(), msg, sourcefile, lineno);
	}
	/* Verbose() output: no syslog, no source info */
	else if (priority == LOG_INFO)
	{
		if (!stdout) return (-1);
		if (errappend)
			fprintf(stdout, "%s[%u]: %s: %s\n", progname, getpid(), msg, strerror(errno));
		else
			fprintf(stdout, "%s[%u]: %s\n", progname, getpid(), msg);
	}
	/* Notice() and Warn() output: syslog, no source info */
	else if (priority == LOG_NOTICE || priority == LOG_WARNING)
	{
		if (errappend)
			syslog(priority, "%s: %m", msg);
		else
			syslog(priority, "%s", msg);
	}
	/* Err(): syslog, with source info */
	else
	{
		if (errappend)
			syslog(priority, "%s%s: %m (%s:%u)", isfatal ? "FATAL: " : "", msg, sourcefile, lineno);
		else
			syslog(priority, "%s%s (%s:%u)", isfatal ? "FATAL: " : "", msg, sourcefile, lineno);
	}

	/* Abort if the error should be fatal */
	if (isfatal)
		exit(EXIT_FAILURE);

#if HAVE_VASPRINTF
	free(msg);
#endif

	return (-1);
}
/*--- _error_out() ------------------------------------------------------------------------------*/


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	_ERROR_SQL
	This function is very similar to the _error_out function in error.c, except that it
	appends the current SQL error message.
	Callers should invoke this function via the ErrSQL and WarnSQL macros.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int
_error_sql(MYSQL *mysql, int isfatal, const char *sourcefile, unsigned int lineno, const char *fmt, ...)
{
#if HAVE_VASPRINTF
	char *msg = NULL;
#else
	char msg[BUFSIZ] = "\0";
#endif
	va_list ap;

	/* Construct output string */
	va_start(ap, fmt);
#if HAVE_VASPRINTF
	vasprintf(&msg, fmt, ap);
#else
	vsnprintf(msg, sizeof(msg), fmt, ap);
#endif
	va_end(ap);

	_error_out(isfatal ? LOG_ERR : LOG_WARNING, 0, isfatal, sourcefile, lineno,
				  "%s: %s (errno=%d)", msg, mysql_error(mysql), errno);

#if HAVE_VASPRINTF
	free(msg);
#endif
	return (-1);
}
/*--- _error_sql() ------------------------------------------------------------------------------*/


/*+************************************************************************************************
   _ERROR_ASSERT_FAIL
   This is called by the macro "Assert" if an assertion fails.
**************************************************************************************************/
void
_error_assert_fail(assertion, file, line)
	const char *assertion;
	const char *file;
	unsigned int line;
{
   _error_out(LOG_ERR, 0, 1, file, line, "assertion failed: %s", assertion);
}
/*--- _error_assert_fail() ----------------------------------------------------------------------*/

/* vi:set ts=3: */
